/**
 * 杭州云霁科技有限公司
 * http://www.idcos.com
 * Copyright (c) 2015 All Rights Reserved.
 */

package com.ls.base.utils;

import com.alibaba.fastjson.JSON;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang.reflect.FieldUtils;
import org.springframework.beans.BeanUtils;

import java.util.Map;

//import org.springframework.util.ReflectionUtils;

/**
 * 封装了对象内部的调用处理
 * @author yanlv
 * @version $Id: ObjectUtil.java, v 0.1 2015年6月17日 上午10:03:37 yanlv Exp $
 */
public class ObjectUtil {

    public static String toString(Object obj) {
        return ToStringBuilder.reflectionToString(obj, ToStringStyle.SHORT_PREFIX_STYLE);
    }

    /**
     * 把对象转化为json字符串格式
     * @param obj
     * @return
     */
    public static String toJSON(Object obj) {
        try {
            return JSON.toJSONString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 把对象转化为map格式,忽略相关的属性
     * @param obj
     * @return
     */

    public static Map<String, Object> toMap(Object obj, String... ignoreProperties) {

        try {


            Map<String, Object> map =PropertyUtils.describe(obj);

            if (ignoreProperties == null || ignoreProperties.length == 0) {
                return map;
            }

            for (String name : ignoreProperties) {
                map.remove(name);
            }

            return map;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 把json字符串转化为class对象
     * @param cls
     * @param json
     * @return
     */
    public static <T> T fromJSON(Class<T> cls, String json) {

        try {
            return JSON.parseObject(json, cls);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * copy两个对象的同名属性
     * @param source
     * @param target
     */
    public static void copyProperties(Object source, Object target) {
        try {
            BeanUtils.copyProperties(source,target);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * copy两个对象的同名属性
     * @param source
     * @param target
     */
    public static void copyProperties(Object source, Object target, String... ignoreProperties) {
        try {
            BeanUtils.copyProperties(source,target,  ignoreProperties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建新对象，并把已有对象的属性值赋给新对象
     * @param source 源对象
     * @param targetClass 目标class
     * @return
     */
    public static <T> T copy(Object source, Class<T> targetClass) {

        try {

            T object = targetClass.newInstance();

            copyProperties(source, object);

            return object;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 设置对象的属性信息 如果对象的属性值为null的话
     * @param source 源对象
     * @param property 属性名称
     * @param value 属性值
     */
    public static void setPropertyIfNull(Object source, String property, Object value) {

        Object val = getProperty(source, property);
        if (val == null) {
            setProperty(source, property, value);
        }
    }

    /**
     * 创建一个对象的实例
     * @param objectClass 对象的类信息
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static final Object newInstance(Class objectClass) {

        try {
            return objectClass.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置对象的属性信息
     * @param source 原对象
     * @param property 属性名称
     * @param value 属性值
     */
    public static void setProperty(Object source, String property, Object value) {

        try {
            FieldUtils.writeField(source, property, value, true);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 获取对象属性值信息
     * @param source 源对象
     * @param propertyName 字段名称
     */
    public static Object getProperty(Object source, String propertyName) {

        return getFieldValue(source, propertyName);

    }

    /**
     * 获取对象字段值信息
     * @param source 源对象
     * @param fieldName 字段名称
     */
    public static Object getFieldValue(Object source, String fieldName) {

        try {
            return FieldUtils.readField(source, fieldName, true);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }

    /* ============================================================================ */
    /*  比较函数。                                                                  */
    /*                                                                              */
    /*  以下方法用来比较两个对象是否相同。                                          */
    /* ============================================================================ */

    /**
     * 比较两个对象是否完全相等。
     *
     * <p>
     * 此方法可以正确地比较多维数组。
     * <pre>
     * ObjectUtil.equals(null, null)                  = true
     * ObjectUtil.equals(null, "")                    = false
     * ObjectUtil.equals("", null)                    = false
     * ObjectUtil.equals("", "")                      = true
     * ObjectUtil.equals(Boolean.TRUE, null)          = false
     * ObjectUtil.equals(Boolean.TRUE, "true")        = false
     * ObjectUtil.equals(Boolean.TRUE, Boolean.TRUE)  = true
     * ObjectUtil.equals(Boolean.TRUE, Boolean.FALSE) = false
     * </pre>
     * </p>
     *
     * @param object1 对象1
     * @param object2 对象2
     *
     * @return 如果相等, 则返回<code>true</code>
     */
    public static boolean equals(Object object1, Object object2) {
        return ArrayUtil.equals(object1, object2);
    }

    /**
     * 把对象转化为可打印的字符串格式，调用
     * @param object
     * @return
     */
    public static String objToString(Object object) {
        if (object == null) {
            return "";
        }

        return ReflectionToStringBuilder.toString(object, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}
